/*
 * @Description  : verilog code from HUIYU
 *                 该代码为对应的串口发送代码，（1bit开始位+8bit数据位+1bit结束位）*8
 * @authorName   : GuoJi
 * @github       : https://github.com/guoji-kk
 * @gitee        : https://gitee.com/guoji13663585559
 * @email        : 13663585559@163.com
 * @version      : 1.0
 * @Date         : 2023-04-14 11:27:57
 * @LastEditTime : 2023-06-08 09:15:09
 */
 
`define  test 
module uart_send64(
    input	      sys_clk,                  //系统时钟
    input         sys_rst_n,                //系统复位，低电平有效
    
    input          uart_en,                  //发送使能信号
    input  [63:0]  uart_din,                 //待发送数据
    output  reg    uart_txd                  //UART发送端口
    );
    
//parameter define
parameter  CLK_FREQ = 12000000;             //系统时钟频率
parameter  UART_BPS = 115200;                 //串口波特率
localparam BPS_CNT  = CLK_FREQ/UART_BPS;    //为得到指定波特率，对系统时钟计数BPS_CNT次
//localparam BPS_CNT = 3;

//reg define
reg        uart_en_d0; 
reg        uart_en_d1;  
reg [15:0] clk_cnt;                         //系统时钟计数器
reg [ 6:0] tx_cnt;                          //发送数据计数器
reg        tx_flag;                         //发送过程标志信号
	  
reg [ 63:0] tx_data;                         //寄存发送数据  


reg [ 4:0] state;                           //状态标志位
//wire define
wire       en_flag;

//捕获uart_en上升沿，得到一个时钟周期的脉冲信号
assign en_flag = (~uart_en_d1) & uart_en_d0;
                                                 
//对发送使能信号uart_en延迟两个时钟周期
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin
        uart_en_d0 <= 1'b0;                                  
        uart_en_d1 <= 1'b0;
    end                                                      
    else begin                                               
        uart_en_d0 <= uart_en;                               
        uart_en_d1 <= uart_en_d0;                            
    end
end

//当脉冲信号en_flag到达时,寄存待发送的数据，并进入发送过程          
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin       	 
        tx_flag <= 1'b1;
        tx_data <= 8'd0;
    end 
    else if (en_flag) begin                 //检测到发送使能上升沿                      
            tx_flag <= 1'b0;                //进入发送过程，标志位tx_flag拉低
            tx_data <= uart_din;            //寄存待发送的数据

        end
        else   if ((tx_cnt == 7'd79)&&(clk_cnt == BPS_CNT/2))
        begin                               //计数到停止位中间时，停止发送过程
            tx_flag <= 1'b1;                //发送过程结束，标志位tx_flag拉高
            tx_data <= 8'h00;
        end
        else begin
            tx_flag <= tx_flag;
            tx_data <= tx_data;
        end 
end

//进入发送过程后，启动系统时钟计数器与发送数据计数器
always @(posedge sys_clk or negedge sys_rst_n) begin         
    if (!sys_rst_n) begin                             
        clk_cnt <= 16'd0;                                  
        tx_cnt  <= 6'd0;
    end                                                      
    else if (!tx_flag) begin                 //处于发送过程
        if (clk_cnt < BPS_CNT - 1) begin
            clk_cnt <= clk_cnt + 1'b1;
            tx_cnt  <= tx_cnt;
        end
        else begin
            clk_cnt <= 16'd0;               //对系统时钟计数达一个波特率周期后清零
            tx_cnt  <= tx_cnt + 1'b1;       //此时发送数据计数器加1
        end
    end
    else begin                              //发送过程结束
        clk_cnt <= 16'd0;
        tx_cnt  <= 6'd0;
    end
end

//根据发送数据计数器来给uart发送端口赋值
always @(posedge sys_clk or negedge sys_rst_n) begin        
    if (!sys_rst_n)  
        uart_txd <= 1'b1;        
    else if (!tx_flag)
        case(tx_cnt)
`ifdef test
            7'd0: uart_txd <= 1'b0;         //起始位 
            7'd1: uart_txd <= tx_data[56];   //数据位最低位
            7'd2: uart_txd <= tx_data[57];
            7'd3: uart_txd <= tx_data[58];
            7'd4: uart_txd <= tx_data[59];
            7'd5: uart_txd <= tx_data[60];
            7'd6: uart_txd <= tx_data[61];
            7'd7: uart_txd <= tx_data[62];
            7'd8: uart_txd <= tx_data[63];   //数据位最高位
            7'd9: uart_txd <= 1'b1;         //停止位
				
			7'd10: uart_txd <= 1'b0;         //起始位 
            7'd11: uart_txd <= tx_data[48];   //数据位最低位
            7'd12: uart_txd <= tx_data[49];
            7'd13: uart_txd <= tx_data[50];
            7'd14: uart_txd <= tx_data[51];
            7'd15: uart_txd <= tx_data[52];
            7'd16: uart_txd <= tx_data[53];
            7'd17: uart_txd <= tx_data[54];
            7'd18: uart_txd <= tx_data[55];   //数据位最高位
            7'd19: uart_txd <= 1'b1;         //停止位
				
			7'd20: uart_txd <= 1'b0;         //起始位 
            7'd21: uart_txd <= tx_data[40];   //数据位最低位
            7'd22: uart_txd <= tx_data[41];
            7'd23: uart_txd <= tx_data[42];
            7'd24: uart_txd <= tx_data[43];
            7'd25: uart_txd <= tx_data[44];
            7'd26: uart_txd <= tx_data[45];
            7'd27: uart_txd <= tx_data[46];
            7'd28: uart_txd <= tx_data[47];   //数据位最高位
            7'd29: uart_txd <= 1'b1;         //停止位

			7'd30: uart_txd <= 1'b0;         //起始位 
            7'd31: uart_txd <= tx_data[32];   //数据位最低位
            7'd32: uart_txd <= tx_data[33];
            7'd33: uart_txd <= tx_data[34];
            7'd34: uart_txd <= tx_data[35];
            7'd35: uart_txd <= tx_data[36];
            7'd36: uart_txd <= tx_data[37];
            7'd37: uart_txd <= tx_data[38];
            7'd38: uart_txd <= tx_data[39];   //数据位最高位
            7'd39: uart_txd <= 1'b1;         //停止位


            7'd40: uart_txd <= 1'b0;         //起始位 
            7'd41: uart_txd <= tx_data[24];   //数据位最低位
            7'd42: uart_txd <= tx_data[25];
            7'd43: uart_txd <= tx_data[26];
            7'd44: uart_txd <= tx_data[27];
            7'd45: uart_txd <= tx_data[28];
            7'd46: uart_txd <= tx_data[29];
            7'd47: uart_txd <= tx_data[30];
            7'd48: uart_txd <= tx_data[31];   //数据位最高位
            7'd49: uart_txd <= 1'b1;         //停止位

            7'd50: uart_txd <= 1'b0;         //起始位 
            7'd51: uart_txd <= tx_data[16];   //数据位最低位
            7'd52: uart_txd <= tx_data[17];
            7'd53: uart_txd <= tx_data[18];
            7'd54: uart_txd <= tx_data[19];
            7'd55: uart_txd <= tx_data[20];
            7'd56: uart_txd <= tx_data[21];
            7'd57: uart_txd <= tx_data[22];
            7'd58: uart_txd <= tx_data[23];   //数据位最高位
            7'd59: uart_txd <= 1'b1;         //停止位

            7'd60: uart_txd <= 1'b0;         //起始位 
            7'd61: uart_txd <= tx_data[8];   //数据位最低位
            7'd62: uart_txd <= tx_data[9];
            7'd63: uart_txd <= tx_data[10];
            7'd64: uart_txd <= tx_data[11];
            7'd65: uart_txd <= tx_data[12];
            7'd66: uart_txd <= tx_data[13];
            7'd67: uart_txd <= tx_data[14];
            7'd68: uart_txd <= tx_data[15];   //数据位最高位
            7'd69: uart_txd <= 1'b1;         //停止位

            7'd70: uart_txd <= 1'b0;         //起始位 
            7'd71: uart_txd <= tx_data[0];   //数据位最低位
            7'd72: uart_txd <= tx_data[1];
            7'd73: uart_txd <= tx_data[2];
            7'd74: uart_txd <= tx_data[3];
            7'd75: uart_txd <= tx_data[4];
            7'd76: uart_txd <= tx_data[5];
            7'd77: uart_txd <= tx_data[6];
            7'd78: uart_txd <= tx_data[7];   //数据位最高位
            7'd79: uart_txd <= 1'b1;         //停止位

`else
			7'd0: uart_txd <= 1'b0;         //起始位 
            7'd1: uart_txd <= tx_data[0];   //数据位最低位
            7'd2: uart_txd <= tx_data[1];
            7'd3: uart_txd <= tx_data[2];
            7'd4: uart_txd <= tx_data[3];
            7'd5: uart_txd <= tx_data[4];
            7'd6: uart_txd <= tx_data[5];
            7'd7: uart_txd <= tx_data[6];
            7'd8: uart_txd <= tx_data[7];   //数据位最高位
            7'd9: uart_txd <= 1'b1;         //停止位
`endif
            default: ;
        endcase
    else 
        uart_txd <= 1'b1;                   //空闲时发送端口为高电平
end

endmodule